{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# 聪明办法学 Python 2nd Edition\n",
    "## Chapter 5 循环 Loop\n",
    "---\n",
    "聪明办法学 Python 教学团队\n",
    "\n",
    "<p>learn.python.the.smart.way@gmail.com</p>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## for 循环和循环范围"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### for 循环的特点\n",
    "\n",
    "基于提供的范围，**重复执行特定次数**的操作"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:15:38.123838Z",
     "start_time": "2023-09-09T11:15:38.106111Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "def sumFromMToN(m, n):\n",
    "    total = 0\n",
    "    # 注意： range(x, y) 是左闭右开区间，包含 x，不包含 y\n",
    "    for x in range(m, n+1):\n",
    "        total += x\n",
    "    return total"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-13T10:41:28.072523Z",
     "start_time": "2023-04-13T10:41:28.064277Z"
    },
    "run_control": {
     "marked": false
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "45"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sumFromMToN(5, 10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-13T10:41:49.810724Z",
     "start_time": "2023-04-13T10:41:49.799724Z"
    },
    "scrolled": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sumFromMToN(5, 10) == 5+6+7+8+9+10"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "### `range()` 是个什么东西？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "其实在这里，我们也可以**不用循环**来完成同样的任务"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:15:06.663138Z",
     "start_time": "2023-09-09T11:15:06.650933Z"
    },
    "init_cell": true,
    "run_control": {
     "marked": false
    },
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [],
   "source": [
    "def sumFromMToN(m, n):\n",
    "    return sum(range(m, n+1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-13T10:51:09.868360Z",
     "start_time": "2023-04-13T10:51:09.862366Z"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "45"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sumFromMToN(5, 10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "如果我们**省略第一个参数**会发生什么？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:15:06.678677Z",
     "start_time": "2023-09-09T11:15:06.665141Z"
    },
    "init_cell": true,
    "run_control": {
     "marked": false
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "def sumToN(n):\n",
    "    total = 0\n",
    "    # range 起始范围默认为 0\n",
    "    for x in range(n+1):\n",
    "        total += x\n",
    "    return total"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-13T10:53:39.381783Z",
     "start_time": "2023-04-13T10:53:39.377799Z"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "15"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sumToN(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "那如果我们添加第三个参数呢？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:15:06.693906Z",
     "start_time": "2023-09-09T11:15:06.680679Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "def sumEveryKthFromMToN(m, n, k):\n",
    "    total = 0\n",
    "    # 第三个参数为 “步长” step\n",
    "    for x in range(m, n+1, k):\n",
    "        total += x\n",
    "    return total"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-13T10:54:08.785897Z",
     "start_time": "2023-04-13T10:54:08.766579Z"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sumEveryKthFromMToN(5, 20, 7) == (5 + 12 + 19)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "只对从 `m` 到 `n` 的 **奇数求和**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:15:06.709367Z",
     "start_time": "2023-09-09T11:15:06.695823Z"
    },
    "init_cell": true,
    "scrolled": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "# 我们也可以通过修改循环内部的代码来改变步长\n",
    "\n",
    "def sumOfOddsFromMToN(m, n):\n",
    "    total = 0\n",
    "    for x in range(m, n+1):\n",
    "        if x % 2 == 1:\n",
    "            total += x\n",
    "    return total"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-13T10:58:37.381818Z",
     "start_time": "2023-04-13T10:58:37.373821Z"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sumOfOddsFromMToN(4, 10) == sumOfOddsFromMToN(5,9) == (5+7+9)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "现在我们**反着来**试一下！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:15:06.724945Z",
     "start_time": "2023-09-09T11:15:06.711370Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "# 我们将生成一个反向数字序列\n",
    "# (仅供演示使用，代码实践中不建议这么做)\n",
    "\n",
    "def sumOfOddsFromMToN(m, n):\n",
    "    total = 0\n",
    "    for x in range(n, m-1, -1):\n",
    "        if x % 2 == 1:\n",
    "            total += x\n",
    "    return total"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-13T11:01:09.536699Z",
     "start_time": "2023-04-13T11:01:09.523712Z"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sumOfOddsFromMToN(4, 10) == sumOfOddsFromMToN(5,9) == (5+7+9)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "还有更多方法来解决这个问题"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# for 循环嵌套"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:20:16.196983Z",
     "start_time": "2023-09-09T11:20:16.188967Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "# 下面的代码将输出二维坐标\n",
    "\n",
    "def printCoordinates(xMax, yMax):\n",
    "    for x in range(1, xMax+1):\n",
    "        for y in range(1, yMax+1):\n",
    "            print(f\"( {x} , {y} )  \", end=\"\")\n",
    "        print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:20:18.149064Z",
     "start_time": "2023-09-09T11:20:18.136933Z"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "( 1 , 1 )  ( 1 , 2 )  ( 1 , 3 )  ( 1 , 4 )  ( 1 , 5 )  \n",
      "( 2 , 1 )  ( 2 , 2 )  ( 2 , 3 )  ( 2 , 4 )  ( 2 , 5 )  \n",
      "( 3 , 1 )  ( 3 , 2 )  ( 3 , 3 )  ( 3 , 4 )  ( 3 , 5 )  \n",
      "( 4 , 1 )  ( 4 , 2 )  ( 4 , 3 )  ( 4 , 4 )  ( 4 , 5 )  \n",
      "( 5 , 1 )  ( 5 , 2 )  ( 5 , 3 )  ( 5 , 4 )  ( 5 , 5 )  \n"
     ]
    }
   ],
   "source": [
    "printCoordinates(5, 5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:15:06.756279Z",
     "start_time": "2023-09-09T11:15:06.743036Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "        <iframe\n",
       "            width=\"1300\"\n",
       "            height=\"800\"\n",
       "            src=\"https://pythontutor.com/visualize.html#code=%23%20%E4%B8%8B%E9%9D%A2%E7%9A%84%E4%BB%A3%E7%A0%81%E5%B0%86%E8%BE%93%E5%87%BA%E4%BA%8C%E7%BB%B4%E5%9D%90%E6%A0%87%0A%0Adef%20printCoordinates%28xMax,%20yMax%29%3A%0A%20%20%20%20for%20x%20in%20range%281,%20xMax%2B1%29%3A%0A%20%20%20%20%20%20%20%20for%20y%20in%20range%281,%20yMax%2B1%29%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20print%28f%22%28%20%7Bx%7D%20,%20%7By%7D%20%29%20%20%22,%20end%3D%22%22%29%0A%20%20%20%20%20%20%20%20print%28%29%0A%20%20%20%20%20%20%20%20%0AprintCoordinates%283,%203%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false\"\n",
       "            frameborder=\"0\"\n",
       "            allowfullscreen\n",
       "            \n",
       "        ></iframe>\n",
       "        "
      ],
      "text/plain": [
       "<IPython.lib.display.IFrame at 0x233782b5850>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import IFrame\n",
    "IFrame('https://pythontutor.com/visualize.html#code=%23%20%E4%B8%8B%E9%9D%A2%E7%9A%84%E4%BB%A3%E7%A0%81%E5%B0%86%E8%BE%93%E5%87%BA%E4%BA%8C%E7%BB%B4%E5%9D%90%E6%A0%87%0A%0Adef%20printCoordinates%28xMax,%20yMax%29%3A%0A%20%20%20%20for%20x%20in%20range%281,%20xMax%2B1%29%3A%0A%20%20%20%20%20%20%20%20for%20y%20in%20range%281,%20yMax%2B1%29%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20print%28f%22%28%20%7Bx%7D%20,%20%7By%7D%20%29%20%20%22,%20end%3D%22%22%29%0A%20%20%20%20%20%20%20%20print%28%29%0A%20%20%20%20%20%20%20%20%0AprintCoordinates%283,%203%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false', width=1300, height=800)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "如果换成 `*` 呢？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:21:27.740635Z",
     "start_time": "2023-09-09T11:21:27.729124Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "def Stars(n, m):\n",
    "    # 输出一个 n*m 的星型矩阵图\n",
    "    for row in range(n):\n",
    "        for col in range(m):\n",
    "            print(\"*\", end=\"\")\n",
    "        print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:21:29.382390Z",
     "start_time": "2023-09-09T11:21:29.368830Z"
    },
    "scrolled": false,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*****\n",
      "*****\n",
      "*****\n",
      "*****\n",
      "*****\n"
     ]
    }
   ],
   "source": [
    "Stars(5, 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "换一种写法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:21:33.438951Z",
     "start_time": "2023-09-09T11:21:33.426301Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "# be careful! 这些代码与之前的有什么不同？\n",
    "\n",
    "def printMysteryStarShape(n):\n",
    "    for row in range(n):\n",
    "        print(row, end=\" \")\n",
    "        for col in range(row):\n",
    "            print(\"*\", end=\" \")\n",
    "        print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:21:36.463755Z",
     "start_time": "2023-09-09T11:21:36.455750Z"
    },
    "scrolled": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 \n",
      "1 * \n",
      "2 * * \n",
      "3 * * * \n",
      "4 * * * * \n"
     ]
    }
   ],
   "source": [
    "printMysteryStarShape(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:21:41.218727Z",
     "start_time": "2023-09-09T11:21:41.211703Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "        <iframe\n",
       "            width=\"1300\"\n",
       "            height=\"800\"\n",
       "            src=\"https://pythontutor.com/visualize.html#code=%23%20be%20careful!%20%E8%BF%99%E4%BA%9B%E4%BB%A3%E7%A0%81%E4%B8%8E%E4%B9%8B%E5%89%8D%E7%9A%84%E6%9C%89%E4%BB%80%E4%B9%88%E4%B8%8D%E5%90%8C%EF%BC%9F%0A%0Adef%20printMysteryStarShape%28n%29%3A%0A%20%20%20%20for%20row%20in%20range%28n%29%3A%0A%20%20%20%20%20%20%20%20print%28row,%20end%3D%22%20%22%29%0A%20%20%20%20%20%20%20%20for%20col%20in%20range%28row%29%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20print%28%22*%22,%20end%3D%22%20%22%29%0A%20%20%20%20%20%20%20%20print%28%29%0A%20%20%20%20%20%20%20%20%0AprintMysteryStarShape%285%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false\"\n",
       "            frameborder=\"0\"\n",
       "            allowfullscreen\n",
       "            \n",
       "        ></iframe>\n",
       "        "
      ],
      "text/plain": [
       "<IPython.lib.display.IFrame at 0x233781b3a60>"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import IFrame\n",
    "IFrame('https://pythontutor.com/visualize.html#code=%23%20be%20careful!%20%E8%BF%99%E4%BA%9B%E4%BB%A3%E7%A0%81%E4%B8%8E%E4%B9%8B%E5%89%8D%E7%9A%84%E6%9C%89%E4%BB%80%E4%B9%88%E4%B8%8D%E5%90%8C%EF%BC%9F%0A%0Adef%20printMysteryStarShape%28n%29%3A%0A%20%20%20%20for%20row%20in%20range%28n%29%3A%0A%20%20%20%20%20%20%20%20print%28row,%20end%3D%22%20%22%29%0A%20%20%20%20%20%20%20%20for%20col%20in%20range%28row%29%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20print%28%22*%22,%20end%3D%22%20%22%29%0A%20%20%20%20%20%20%20%20print%28%29%0A%20%20%20%20%20%20%20%20%0AprintMysteryStarShape%285%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false', width=1300, height=800)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# while 循环"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "# 嘿！"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "source": [
    "当你**不知道循环什么时候停下来**的时候，为什么不试试 **`while`**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "找出一个数最左边的那一位的数值（`12345` 的 `1` ）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:21:55.773889Z",
     "start_time": "2023-09-09T11:21:55.762274Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "# 我不知道它什么时候停下来\n",
    "\n",
    "def leftmostDigit(n):\n",
    "    n = abs(n)\n",
    "    while n >= 10:\n",
    "        n = n//10\n",
    "    return n "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:21:57.020796Z",
     "start_time": "2023-09-09T11:21:57.013235Z"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "leftmostDigit(46535248)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "举个例子：依次找出 n 个 4 或者 7 的整数倍非负整数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:21:59.804976Z",
     "start_time": "2023-09-09T11:21:59.800978Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "def isMultipleOf4or7(x):\n",
    "    return ((x % 4) == 0) or ((x % 7) == 0)\n",
    "\n",
    "def nthMultipleOf4or7(n):\n",
    "    found = 0\n",
    "    guess = -1\n",
    "    while found <= n:\n",
    "        guess += 1\n",
    "        if isMultipleOf4or7(guess):\n",
    "            found += 1\n",
    "    return guess"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:22:12.475935Z",
     "start_time": "2023-09-09T11:22:12.463263Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4 或 7 的倍数: 0 4 7 8 12 14 16 20 21 24 28 32 35 36 40 "
     ]
    }
   ],
   "source": [
    "print(\"4 或 7 的倍数: \", end=\"\")\n",
    "for n in range(15):\n",
    "    print(nthMultipleOf4or7(n), end=\" \")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "**Bad Style**：在知道循环范围的情况下使用 `while`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:22:15.525237Z",
     "start_time": "2023-09-09T11:22:15.515126Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "def sumToN(n):\n",
    "    # 尽管它能正确运行，但是这是非常不推荐的做法！\n",
    "    # 应该使用 for 循环而不是 while 循环\n",
    "    total = 0\n",
    "    counter = 1\n",
    "    while counter <= n:\n",
    "        total += counter\n",
    "        counter += 1\n",
    "    return total"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:22:20.446712Z",
     "start_time": "2023-09-09T11:22:20.442047Z"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sumToN(5) == 1+2+3+4+5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# break 与 continue 语句"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:22:23.392061Z",
     "start_time": "2023-09-09T11:22:23.388060Z"
    },
    "run_control": {
     "marked": false
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 4 5 7 "
     ]
    }
   ],
   "source": [
    "for n in range(200):\n",
    "    if n % 3 == 0:\n",
    "        continue # 跳过这次循环\n",
    "    elif n == 8:\n",
    "        break # 跳出当前整个循环\n",
    "    else:\n",
    "        pass # 啥也不做，占位符（不会被运行）\n",
    "    print(n, end=\" \")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## 假·死循环\n",
    "\n",
    "与环境交互后，在特定条件下终止的循环"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:22:30.144987Z",
     "start_time": "2023-09-09T11:22:30.138988Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "# 不需要看懂这些代码，关注演示的过程\n",
    "\n",
    "def readUntilDone():\n",
    "    linesEntered = 0\n",
    "    while True:\n",
    "        response = input(\"输入一个字符串（输入 done 则退出）: \")\n",
    "        if response == \"done\":\n",
    "            break\n",
    "        print(\"你输入了: \", response)\n",
    "        linesEntered += 1\n",
    "    print(\"Bye!\")\n",
    "    return linesEntered"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:23:02.381027Z",
     "start_time": "2023-09-09T11:22:33.604132Z"
    },
    "scrolled": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你输入了:  learn\n",
      "你输入了:  python\n",
      "你输入了:  the\n",
      "你输入了:  smart\n",
      "你输入了:  way\n",
      "Bye!\n",
      "你输入了 5 行 (不包括 'done').\n"
     ]
    }
   ],
   "source": [
    "linesEntered = readUntilDone()\n",
    "print(\"你输入了\", linesEntered, \"行 (不包括 'done').\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "<big>isPrime</big>\n",
    "\n",
    "判断一个数是不是质数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:23:21.885263Z",
     "start_time": "2023-09-09T11:23:21.876682Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [],
   "source": [
    "# 不是最快的写法，但最容易理解\n",
    "\n",
    "def isPrime(n):\n",
    "    if n < 2:\n",
    "        return False\n",
    "    for factor in range(2,n):\n",
    "        if n % factor == 0:\n",
    "            return False\n",
    "    return True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:23:25.358837Z",
     "start_time": "2023-09-09T11:23:25.341650Z"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 "
     ]
    }
   ],
   "source": [
    "for n in range(100):\n",
    "    if isPrime(n):\n",
    "        print(n, end=\" \")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "<big>faster IsPrime</big>:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:23:29.618975Z",
     "start_time": "2023-09-09T11:23:29.613707Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "# 快了一点\n",
    "\n",
    "def fasterIsPrime(n):\n",
    "    if n < 2:\n",
    "        return False\n",
    "    if n == 2:\n",
    "        return True\n",
    "    if n % 2 == 0:\n",
    "        return False\n",
    "    maxFactor = round(n**0.5)\n",
    "    for factor in range(3, maxFactor+1, 2):\n",
    "        if n % factor == 0:\n",
    "            return False\n",
    "    return True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:23:44.904782Z",
     "start_time": "2023-09-09T11:23:44.901221Z"
    },
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 "
     ]
    }
   ],
   "source": [
    "for n in range(100):\n",
    "    if fasterIsPrime(n):\n",
    "        print(n, end=\" \")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "## 真的快了？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:23:47.546067Z",
     "start_time": "2023-09-09T11:23:47.533521Z"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "两种解法的结果一致\n"
     ]
    }
   ],
   "source": [
    "# 验证他它俩结果是一样的\n",
    "for n in range(100):\n",
    "    assert(isPrime(n) == fasterIsPrime(n))\n",
    "print(\"两种解法的结果一致\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:25:59.566775Z",
     "start_time": "2023-09-09T11:25:54.772969Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Timing isPrime( 102030407 ) , returns  True , time =  4708.568811416626 ms\n",
      "\n",
      "Timing fasterIsPrime( 102030407 ) , returns  True , time =  0.4515647888183594 ms\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "\n",
    "bigPrime = 102030407\n",
    "print(\"Timing isPrime(\",bigPrime,\")\", end=\" \")\n",
    "\n",
    "# isPrime\n",
    "time0 = time.time()\n",
    "print(\", returns \", isPrime(bigPrime), end=\" \")\n",
    "\n",
    "time1 = time.time()\n",
    "print(\", time = \",(time1-time0)*1000,\"ms\\n\")\n",
    "\n",
    "# fasterIsPrime\n",
    "print(\"Timing fasterIsPrime(\",bigPrime,\")\", end=\" \")\n",
    "time0 = time.time()\n",
    "\n",
    "print(\", returns \", fasterIsPrime(bigPrime), end=\" \")\n",
    "time1 = time.time()\n",
    "\n",
    "# result\n",
    "print(\", time = \",(time1-time0)*1000,\"ms\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "subslide"
    }
   },
   "source": [
    "<big>nth Prime</big>\n",
    "\n",
    "依次找出第 n 位质数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-09-09T11:15:11.709393Z",
     "start_time": "2023-09-09T11:15:11.695849Z"
    },
    "init_cell": true,
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "def nthPrime(n):\n",
    "    found = 0\n",
    "    guess = 0\n",
    "    while found <= n:\n",
    "        guess += 1\n",
    "        if fasterIsPrime(guess):\n",
    "            found += 1\n",
    "    return guess"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-04-13T12:00:57.641785Z",
     "start_time": "2023-04-13T12:00:57.624787Z"
    },
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 2\n",
      "1 3\n",
      "2 5\n",
      "3 7\n",
      "4 11\n",
      "5 13\n",
      "6 17\n",
      "7 19\n",
      "8 23\n",
      "9 29\n",
      "Done!\n"
     ]
    }
   ],
   "source": [
    "for n in range(10):\n",
    "    print(n, nthPrime(n))\n",
    "print(\"Done!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 总结\n",
    "\n",
    "- For 循环用于指定范围的重复操作。\n",
    "- `range()` 可以生成一个数字范围。\n",
    "- 在不知道循环什么时间停止的时候，应该试试 While 循环。\n",
    "- 循环同样也是可以嵌套的。\n",
    "- 巧妙地使用 `break` 和 `continue` 语句。\n",
    "- 合理的剪枝，缩小搜索范围/循环范围，可以大幅提高程序运行效率。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Thank You ;-)\n",
    "Datawhale 聪明办法学 Python 教学团队出品\n",
    "\n",
    "## 关注我们\n",
    "Datawhale 是一个专注 AI 领域的开源组织，以“for the learner，和学习者一起成长”为愿景，构建对学习者最有价值的开源学习社区。关注我们，一起学习成长。\n",
    "\n",
    "<div align=center><img src=\"../resources/datawhale_wechat_qrcode.jpeg\" width = \"250\" height = \"270\"></div>"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  },
  "rise": {
   "overlay": "<div class='my-top-right'><img height=40px src='../resources/datawhale_logo.png'/></div><div class='my-top-left'></div>"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  },
  "vscode": {
   "interpreter": {
    "hash": "2604979e475c72c3999e63049dbb75eb38f7d29b6d0ace0384f7e020f0ee1ffa"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
